package com.alibaba.aliper.core.chart;

import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.SymbolAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYAreaRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;


/**
 * 基于JFreeChart实现的AliperChart.
 * 用于实时展示监控数据的多维度的图表
 * @author cori-chenxx
 *
 */
public class AliperChart {
	/**
	 * 绘制图板。每个绘制图板包括一个坐标，一个标题和相应的绘制曲线。
	 * 可以通过AliperChart申请新的绘制图板。
	 * 但是，同一个AlilperChart中不能同时存在同名的图板。
	 * @author cori-chenxx
	 *
	 */
	public class AliperLine implements IFill{
		public AliperLine(String title,Color color,boolean isArea,int id){
			this.titile = title;
			this.id = id;
			this.series =  new TimeSeries(this.titile,Millisecond.class);
			XYPlot plot = chart.getXYPlot();
			
			if(!AliperChart.this.shareAxias){
				NumberAxis axis = new NumberAxis(title);
				axis.setFixedDimension(10.0);
				axis.setAutoRangeIncludesZero(false);
				axis.setLabelPaint(color);
				axis.setTickLabelPaint(color);
				plot.setRangeAxis(id, axis);
			}

			XYItemRenderer renderer = null;
			if(isArea){
				renderer = new XYAreaRenderer();
				renderer.setSeriesPaint(0, color);
			}else{
				renderer = new StandardXYItemRenderer();
				renderer.setSeriesPaint(0, color);
			}
			plot.setRenderer(id, renderer);
		}
		private String titile = "default title";
		private int id = 0;
	    private long lastTime = -1;
		@Override
		public synchronized void fill(long time, double data) {
			if(AliperChart.this.start == null){
				start = new Millisecond(new Date(time));
			}
			RegularTimePeriod period = new Millisecond(new Date(time));
			for(int j = 0; j < time - lastTime && lastTime > 0; ++j)
				period = period.next();
			series.addOrUpdate(period, data);
			this.render();
			lastTime = time;
		}
		private void render() {
			//将当前画板的缓冲数据渲染到图表
			XYPlot plot = chart.getXYPlot();
			TimeSeriesCollection dataset = new TimeSeriesCollection();
			dataset.addSeries(series);
			plot.setDataset(id, dataset);
			if(AliperChart.this.shareAxias){
				plot.mapDatasetToRangeAxis(id, 0);
			}
			else
				plot.mapDatasetToRangeAxis(id, id);
		}

		 TimeSeries series = null;

	}
	private boolean shareAxias = false;
	private NumberAxis sharedAxis;
	public AliperChart(String title,String subTitle,Color background){
		this(title,subTitle,background,false);
	}
	public AliperChart(String title,String subTitle,Color background,boolean shareAxias){
		chart = ChartFactory.createTimeSeriesChart(title, "Time of Day", null,null, true, true, false);
		if(subTitle != null)
			chart.addSubtitle(new TextTitle(subTitle));
		if(background != null)
			chart.setBackgroundPaint(background);
		this.shareAxias  = shareAxias;
		if(shareAxias){
			sharedAxis = new NumberAxis(title);
			sharedAxis.setFixedDimension(10.0);
			sharedAxis.setAutoRangeIncludesZero(false);
			sharedAxis.setLabelPaint(Color.black);
			sharedAxis.setTickLabelPaint(Color.black);
			chart.getXYPlot().setRangeAxis(0,sharedAxis);
		}
	}
	private JFreeChart chart ;
	private HashMap<String, AliperLine> lines = new HashMap<String, AliperLine>();
	private RegularTimePeriod start = null;

	public JFreeChart getChart(){
		return chart;
	}
	public synchronized byte[] getImageData(int width,int height) throws IOException {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		ChartUtilities.writeChartAsJPEG(stream, chart, width, height);
		return stream.toByteArray();
	}
	public synchronized IFill getLine(String title,Color color,boolean isArea){
		if( !lines.containsKey(title)){
			lines.put(title, new AliperLine(title, color, isArea,lines.size()));
		}
		return lines.get(title);
	}
	public static void main(String[] args) throws InterruptedException {
		AliperChart alipChart = new AliperChart("性能统计", "阿里巴巴质量保证部出品(cori.chenxx)",Color.LIGHT_GRAY,true);
		IFill res = alipChart.getLine("响应时间", Color.red,false);
		IFill tps = alipChart.getLine("tps", Color.black,false);
		ChartFrame frame = new ChartFrame("Aliper", alipChart.getChart());
		frame.setSize(800, 400);
		frame.setVisible(true);
		
		Random ran = new Random();
		int olda = 50;
		int oldb = 70;
		for(int i = 0; i < 200; ++ i ){
			res.fill(System.currentTimeMillis(),olda += ran.nextInt(10)  );
			tps.fill(System.currentTimeMillis(),oldb += ran.nextInt(50) );
			Thread.sleep(300);
		}

	}
	public Collection<AliperLine> getLines() {
		return this.lines.values();
	}
	public int getLineCount(){
		return this.lines.size();
	}
	private static Color[] colors = new Color[]{Color.GREEN,Color.DARK_GRAY,Color.RED,Color.BLUE};
	public IFill getLine(String title, boolean isArea) {
		int index = this.lines.size();
		if(index < colors.length){
			return getLine(title, colors[index], isArea);
		} else {
			return getLine(title, Color.BLACK, isArea);
		}
	}
}
